package demo.combination;


import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.List;
import java.util.Stack;

/**
 * @author : feixiang.li
 * @since : 2025-09-17 14:59
 */
public class ExpressParser {
    private String infixExpression;

    public ExpressParser(String infixExpression) {
        this.infixExpression = infixExpression;

    }

    Expression parse() {
        List<String> suffix = toSuffix(infixExpression);
        return toExpression(suffix);
    }

    public Expression toExpression(List<String> suffix) {
        ArrayDeque<Expression> stack2 = new ArrayDeque<>();
        for (String s : suffix) {
            if (s.equals("+")) {
                Expression right = stack2.pop();
                Expression left = stack2.pop();
                stack2.push(new AddExpression(left, right));
            } else if (s.equals("-")) {
                Expression right = stack2.pop();
                Expression left = stack2.pop();
                stack2.push(new SubstractExpression(left, right));
            } else if (s.equals("*")) {
                Expression right = stack2.pop();
                Expression left = stack2.pop();
                stack2.push(new MultiplyExpression(left, right));
            } else if (s.equals("/")) {
                Expression right = stack2.pop();
                Expression left = stack2.pop();
                stack2.push(new DevisionExpression(left, right));
            } else {
                stack2.push(new NumberExpression(Integer.parseInt(s)));
            }
        }
        return stack2.pop();
    }

    public List<String> toSuffix(String express) {
        List<String> expressList = new ArrayList<>();
        ArrayDeque<Character> stack1 = new ArrayDeque<>();
        int i = 0;
        while (i < express.length()) {
            char c = express.charAt(i);
            if (Character.isDigit(c)) {
                StringBuilder number = new StringBuilder();
                while (i < express.length() && Character.isDigit(express.charAt(i))) {
                    number.append(express.charAt(i));
                    i++;
                }
                i--;
                expressList.add(number.toString());
            } else if (c == '(') {
                // 括号
                stack1.push(c);
            }
            // 需要一直弹出栈顶元素，直到遇到左括号
            if (c == ')') {
                // 括号
                while (!stack1.isEmpty() && stack1.peek() != '(') {
                    expressList.add(Character.toString(stack1.pop()));
                }
                stack1.pop();
            } else if (c == '+' || c == '-') {
                while (!stack1.isEmpty() && (stack1.peek() == '-' || stack1.peek() == '+' || stack1.peek() == '*' || stack1.peek() == '/')) {
                    expressList.add(Character.toString(stack1.pop()));
                }
                stack1.push(c);
            } else if (c == '*' || c == '/') {
                // 让辅助栈中的 大于等于自己的运算符 add 到结果集
                while (!stack1.isEmpty() && (stack1.peek() == '*' || stack1.peek() == '/')) {
                    expressList.add(Character.toString(stack1.pop()));
                }
                stack1.push(c);
            }
            i++;
        }
        while (!stack1.isEmpty()) {
            expressList.add(Character.toString(stack1.pop()));
        }
        return expressList;
    }
}
